import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.util.Map;

import com.speljohan.rsbot.bot.Bot;
import com.speljohan.rsbot.event.events.ServerMessageEvent;
import com.speljohan.rsbot.event.listeners.PaintListener;
import com.speljohan.rsbot.event.listeners.ServerMessageListener;
import com.speljohan.rsbot.script.Constants;
import com.speljohan.rsbot.script.Methods;
import com.speljohan.rsbot.script.Script;
import com.speljohan.rsbot.script.wrappers.RSInterface;
import com.speljohan.rsbot.script.wrappers.RSItem;
import com.speljohan.rsbot.script.wrappers.RSNPC;
import com.speljohan.rsbot.script.wrappers.RSObject;
import com.speljohan.rsbot.script.wrappers.RSTile;

public class AlKharidLeather extends Script implements PaintListener,
		ServerMessageListener {
	private final long startTime = System.currentTimeMillis();
	private final int threadID = 1734, bankID = 35647, tannerID = 2824,
			coinsID = 995, wait1 = 400, wait2 = 600;
	private int working, count, made, level, hideLeftX, hideRightX, hideTopY,
			hideBottomY, minX, maxX, minY, maxY, cowHideID, needleID = 1733;
	private final int[] leatherID = { 1741, 1743, 2509, 2505, 1745, 2507 };
	private String make, doing;
	final String amount = "1000";
	private final RSTile bankTile = new RSTile(3271, 3167),
			midTile = new RSTile(3277, 3176), tannerTile = new RSTile(3274,
					3191);
	private boolean crafting = false, paying, swit = false, members = false;
	private final RSTile[] path = { bankTile, midTile, tannerTile };

	private RSTile checkTile(final RSTile tile) {
		if (tileOnMap(tile)) {
			return tile;
		}
		final RSTile loc = getMyPlayer().getLocation();
		final RSTile walk = new RSTile((loc.getX() + tile.getX()) / 2, (loc
				.getY() + tile.getY()) / 2);
		return tileOnMap(walk) ? walk : checkTile(walk);
	}

	private RSItem findItem() {
		final int[] items = getInventoryArray();
		RSItem leather = null;
		for (int i = items.length - 1; i > 0; i--) {
			for (final int l : leatherID) {
				if (l == items[i]) {
					leather = new RSItem(items[i], 1);
				}
			}
		}
		return leather;
	}

	@Override
	public String getAuthor() {
		return "Fusion89k";
	}

	@Override
	public String getName() {
		return "Al Kharid Leather";
	}

	@Override
	public String getScriptCategory() {
		return "Crafting";
	}

	@Override
	public String getScriptDescription() {
		return "<html>\n"
				+ "<head></head>\n"
				+ "<body>\n"
				+ "<center>"
				+ "<h2>"
				+ getName()
				+ "</h2>"
				+ "</center>\n"
				+ "<b>Author:</b> "
				+ getAuthor()
				+ "<br />"
				+ "<b>Version:</b> "
				+ getVersion()
				+ "<br><br>"
				+ "<form>Crafting: <input type=\"radio\" name=\"type\" value=\"1\"checked=\"checked\">&nbsp;&nbsp;&nbsp;&nbsp;Tanning: <input type=\"radio\" name=\"type\" value=\"2\">"
				+ "</form><br><br><form>Crafting: <select name=\"what\"><option>Gloves<option>Boots<option>Cowl<option>Vambraces<option>Soft Body<option>Chaps<option>Hard Body<option>Coif</select>"
				+ "    AutoSwitch: <input type=\"checkbox\" name=\"switch\" value=\"1\" checked=\"checked\">&nbsp;&nbsp<input type='checkbox' name='member' value='1'>Clay Needle</form>"
				+ "<form><br>Tanning: <select name=\"leather\"><option>Leather<option>Hard Leather<option>Snake Skin (15)<option>Snake Skin(20)<option>Green Hide<option>Blue Hide<option>Red Hide<option>Black Hide</select></form>"
				+ "</body>\n" + "</html>";
	}

	private RSTile getTile() {
		RSTile min = path[0];
		for (int i = 1; i < path.length; i++) {
			if (distanceTo(path[i]) < distanceTo(min)) {
				min = path[i];
			}
		}
		return min;
	}

	@Override
	public double getVersion() {
		return 1.5;
	}

	private boolean isMoving() {
		if (!getMyPlayer().isMoving()) {
			return false;
		}
		if (getDestination() != null
				&& Methods.distanceBetween(path[0], getDestination()) > 5
				&& Methods.distanceBetween(path[path.length - 1],
						getDestination()) > 5) {
			if (distanceTo(getDestination()) < 6) {
				return false;
			}
		}
		return true;
	}

	@Override
	public int loop() {
		setCameraAltitude(true);
		if (isMoving()) {
			return random(wait1, wait2);
		}
		if (paying) {// Buying leather
			if (needBank()) {
				if (distanceTo(bankTile) > 4) {
					doing = "Walking to Bank";
					walk(true);
					return random(wait1, wait2);
				}
				if (!RSInterface.getInterface(Constants.INTERFACE_BANK)
						.isValid()) {
					doing = "Finding Bank";
					final RSObject booth = findObject(bankID);
					if (booth == null) {
						rotate();
						return random(wait1, wait2);
					}
					atObject(booth, "Use-Quickly");
					return random(wait1, wait2);
				}
				if (RSInterface.getInterface(Constants.INTERFACE_BANK)
						.isValid()) {
					doing = "Depositing";
					bank.depositAllExcept(coinsID, cowHideID);
					doing = "Withdrawing";
					if (getInventoryCount(coinsID) < 27) {
						clickMouse(random(82, 117), random(92, 123), false);
						pause();
						if (getMenuIndex(amount) < 0) {
							atMenu("X");
							pause();
							if (!sendTextCustom(amount)) {
								return random(wait1, wait2);
							}
						} else {
							atMenu(amount);
						}
						pause();
						return random(wait1, wait2);
					}
					if (getInventoryCount(cowHideID) < 1) {
						clickMouse(random(38, 73), random(92, 123), false);
						pause();
						atMenu("but");
						return random(wait1, wait2);
					}
					bank.close();
					return random(wait1, wait2);
				}
			} else {
				if (distanceTo(tannerTile) > 4) {
					doing = "Walking to Tanner";
					walk(false);
					return random(wait1, wait2);
				}
				if (!RSInterface.getInterface(324).isValid()) {
					doing = "Opening Tan Screen";
					final RSNPC tan = getNearestNPCByID(tannerID);
					if (tan == null || distanceTo(tan) > 5) {
						rotate();
						return random(wait1, wait2);
					}
					final int temp = random(1, 5);
					if (temp == 1) {
						atInventoryItem(cowHideID, "Use");
						atTile(tan.getLocation(), "Ellis");
					} else {
						atNPC(tan, "Trade");
					}
					return random(wait1, wait2);
				} else {
					doing = "Tanning";
					clickMouse(random(hideLeftX, hideRightX), random(hideTopY,
							hideBottomY), false);
					pause();
					atMenu("All");
				}
				return random(wait1, wait2);
			}
		} else {// Crafting Stuff
			if ((getInventoryCount(needleID) < 1 && !members || getInventoryCount(threadID) < 1)
					&& isLoggedIn()) {
				log("No Equipment - Logging Out");
				stopAllScripts();
			}
			if (needBank()) {
				if (distanceTo(bankTile) > 4) {
					doing = "Walking to bank";
					walk(true);
					return random(wait1, wait2);
				}
				if (!RSInterface.getInterface(Constants.INTERFACE_BANK)
						.isValid()) {
					doing = "Finding Bank";
					final RSObject booth = findObject(bankID);
					if (booth == null) {
						rotate();
						return random(wait1, wait2);
					}
					atObject(booth, "Use-Quickly");
					return random(wait1, wait2);
				}
				if (RSInterface.getInterface(Constants.INTERFACE_BANK)
						.isValid()) {
					doing = "Depositing";

					if (members) {
						final int[] items = new int[leatherID.length + 2];
						for (int i = 0; i < leatherID.length; i++) {
							items[i] = leatherID[i];
						}
						items[items.length - 2] = needleID;
						items[items.length - 1] = threadID;
						bank.depositAllExcept(items);
					} else {
						bank.depositAllExcept(needleID, threadID);
					}
					doing = "Withdrawing";
					if (getInventoryCount(needleID) < 1) {
						final int ran = random(10, 18);
						searchItem("Sacred clay needle".substring(0, ran));
						clickMouse(random(38, 73), random(92, 123), false);
						pause();
						atMenu("1");
						bank.close();
					} else {
						clickMouse(random(38, 73), random(92, 123), false);
						pause();
						atMenu("but");
						bank.close();
					}
					return random(wait1, wait2);
				}
			} else {
				if (crafting) {
					if (getMyPlayer().getAnimation() != -1) {
						count = 0;
					} else {
						if (count < 6) {
							count++;
						} else {
							count = 0;
							crafting = false;
						}
					}
					return random(wait1, wait2);
				}// 309
				if (!RSInterface.getInterface(154).isValid()
						&& !make.contains("Hard")
						|| !RSInterface.getInterface(309).isValid()
						&& make.contains("Hard")) {
					doing = "Threading Needle";
					useItem(new RSItem(needleID, 1), findItem());
					pause();
					return random(wait1, wait2);
				} else {
					if (swit) {// Auto Switch
						doing = "Auto Switch";
						final int curLevel = skills
								.getCurrentSkillLevel(Constants.STAT_CRAFTING);
						if (curLevel < 7) {
							make = "Gloves";
							minX = 144;
							maxX = 233;
							minY = 74;
							maxY = 173;
						} else if (curLevel < 9) {
							make = "Boots";
							minX = 269;
							maxX = 358;
							minY = 74;
							maxY = 173;
						} else if (curLevel < 11) {
							make = "Cowls";
							minX = 344;
							maxX = 433;
							minY = 204;
							maxY = 303;
						} else if (curLevel < 14) {
							make = "Vambraces";
							minX = 384;
							maxX = 473;
							minY = 74;
							maxY = 173;
						} else if (curLevel < 18) {
							make = "Soft Bodies";
							minX = 29;
							maxX = 118;
							minY = 74;
							maxY = 173;
						} else {
							make = "Chaps";
							minX = 84;
							maxX = 173;
							minY = 204;
							maxY = 303;
						}
					}
					doing = "Crafting";
					clickMouse(random(minX, maxX), random(minY, maxY), false);
					pause();
					atMenu("All");
					crafting = true;
					return random(wait1, wait2);
				}
			}
		}
		return random(wait1, wait2);
	}

	private boolean needBank() {
		if (paying) {
			if (getInventoryCount(coinsID) < 27
					|| getInventoryCount(cowHideID) < 1) {
				return true;
			}
		} else {
			if (getInventoryCount(leatherID) < 1) {
				return true;
			}
			if (members && getInventoryCount(needleID) < 1) {
				return true;
			}
		}
		return false;
	}

	@Override
	public void onFinish() {
		Bot.getEventManager().removeListener(PaintListener.class, this);
	}

	public void onRepaint(final Graphics g) {
		if (isLoggedIn()) {
			long millis = System.currentTimeMillis() - startTime;
			final long hours = millis / (1000 * 60 * 60);
			millis -= hours * 1000 * 60 * 60;
			final long minutes = millis / (1000 * 60);
			millis -= minutes * 1000 * 60;
			final long seconds = millis / 1000;
			final int topX = 515 - 173;
			int topY = 337 - 80;
			if (paying) {
				topY = 337 - 55;
			} else {
				topY = 337 - 70;
			}
			final int x = topX + 5;
			int y = topY + 5;
			g.setColor(new Color(0, 100, 0, 100));
			g.fill3DRect(topX, topY, 515 - topX, 337 - topY, true);
			g.setColor(Color.green);
			g.drawString("Runtime: " + hours + "h " + minutes + "min "
					+ seconds + "sec.", x, y += 15);
			g.drawString("Crafted: " + Integer.toString(made) + " " + make
					+ ".", x, y += 15);
			if (!paying) {
				g.drawString("Levels Gained: " + Integer.toString(level) + ".",
						x, y += 15);
			}
			g.drawString("Status: " + doing, x, y += 15);
		}
	}

	@Override
	public boolean onStart(final Map<String, String> args) {
		working = Integer.parseInt(args.get("type"));
		switch (working) {
		case 1:
			paying = false;
			if (args.get("switch") != null) {
				swit = true;
			}
			if (args.get("member") != null) {
				needleID = 14113;
				members = true;
			}
			final char what = args.get("what").toLowerCase().charAt(0);
			switch (what) {
			case 'g':
				make = "Gloves";
				minX = 144;
				maxX = 233;
				minY = 74;
				maxY = 173;
				break;
			case 'b':
				make = "Boots";
				minX = 269;
				maxX = 358;
				minY = 74;
				maxY = 173;
				break;
			case 'v':
				make = "Vambraces";
				minX = 384;
				maxX = 473;
				minY = 74;
				maxY = 173;
				break;
			case 's':
				make = "Soft Bodies";
				minX = 29;
				maxX = 118;
				minY = 74;
				maxY = 173;
				break;
			case 'h':
				make = "Hard Bodies";
				minX = 200;
				maxX = 118;
				minY = 379;
				maxY = 457;
				swit = false;
				break;
			case 'c':
				minY = 204;
				maxY = 303;
				if (args.get("what").charAt(1) == 'o') {
					if (args.get("what").charAt(2) == 'i') {
						make = "Coifs";
						minX = 230;
						maxX = 270;
						swit = false;
					} else {
						make = "Cowls";
						minX = 344;
						maxX = 433;
					}
				} else {
					make = "Chaps";
					minX = 84;
					maxX = 173;
				}
				break;
			}
			break;
		case 2:
			make = "Leather";
			paying = true;
			final char le = args.get("leather").toLowerCase().charAt(0);
			switch (le) {
			case 'l':
				cowHideID = 1739;
				hideLeftX = 44;
				hideRightX = 139;
				hideTopY = 60;
				hideBottomY = 171;
				break;
			case 'h':
				cowHideID = 1739;
				hideLeftX = 156;
				hideRightX = 251;
				hideTopY = 60;
				hideBottomY = 171;
				break;
			case 's':
				hideTopY = 60;
				hideBottomY = 171;
				final char num = args.get("leather").toLowerCase().charAt(
						args.get("leather").length() - 3);
				if (num == '0') {
					cowHideID = 7801;
					hideLeftX = 379;
					hideRightX = 474;
				} else {
					cowHideID = 6287;
					hideLeftX = 267;
					hideRightX = 362;
				}
				break;
			case 'g':
				cowHideID = 1753;
				hideLeftX = 44;
				hideRightX = 139;
				hideTopY = 188;
				hideBottomY = 299;
				break;
			case 'b':
				hideTopY = 188;
				hideBottomY = 299;
				if (args.get("leather").toLowerCase().charAt(2) == 'u') {
					cowHideID = 1751;
					hideLeftX = 156;
					hideRightX = 251;
				} else {
					cowHideID = 1747;
					hideLeftX = 380;
					hideRightX = 475;
				}
				break;
			case 'r':
				cowHideID = 1749;
				hideLeftX = 268;
				hideRightX = 363;
				hideTopY = 188;
				hideBottomY = 299;
				break;
			}
			break;
		}
		return true;
	}

	private void pause() {
		wait(random(wait1, wait2));
	}

	private RSTile randomTile(final RSTile location) {
		return randomTile(location, 2);
	}

	private RSTile randomTile(final RSTile location, final int rand) {
		return randomTile(location, rand, rand);
	}

	private RSTile randomTile(final RSTile location, final int xRand,
			final int yRand) {
		final int x = location.getX(), y = location.getY();
		return new RSTile(x + random((-1 * xRand), xRand), y
				+ random((-1 * yRand), yRand));
	}

	private void rotate() {
		setCameraRotation(getCameraAngle() + random(-10, 10));
	}

	public boolean searchItem(final String itemName) {
		if (!bank.getInterface().isValid()) {
			return false;
		}
		// /random(299,333) random(291,325)
		// atInterface(Constants.INTERFACE_BANK,
		// Constants.INTERFACE_BANK_BUTTON_SEARCH, "Search");
		clickMouse(random(299, 333), random(291, 325), true);
		wait(random(1000, 2000));

		if (bank.getInterface().isValid()
				&& RSInterface.getInterface(Constants.INTERFACE_BANK_SEARCH)
						.isValid()) {
			Bot.getInputManager().sendKeys(itemName, false);
			wait(random(300, 700));
			return true;
		}
		return false;
	}

	private boolean sendTextCustom(final String text) {
		sendText(text, false);
		final String sent = RSInterface.getChildInterface(137, 51).getText();
		if (Character.toString(sent.charAt(sent.length() - 2)).equals(">")) {
			sendKey((char) KeyEvent.VK_ENTER);
			return true;
		}
		for (int i = 0; i < 5; i++) {
			sendKey((char) KeyEvent.VK_BACK_SPACE);
		}
		return false;
	}

	public void serverMessageRecieved(final ServerMessageEvent e) {
		final String word = e.getMessage().toLowerCase();
		if (word.contains("only have one")) {
			log("Out of leather/cowhides - Logging Out");
			bank.close();
			stopAllScripts();
		} else if (word.contains("advanced")) {
			level++;
			crafting = false;
		} else if (word.contains("27")) {
			made += 27;
		} else if (word.contains("make")) {
			made++;
		} else if (word.contains("run of of")) {
			log("Out of thread - Logging Out");
			stopAllScripts();
		}
	}

	private void walk(final boolean toBank) {
		if (getEnergy() >= random(60, 100)) {
			setRun(true);
		}
		final RSTile start = getTile();
		int loc = 0;
		for (int i = 0; i < path.length; i++) {
			if (start.equals(path[i])) {
				loc = i;
				break;
			}
		}
		if (toBank) {
			if (loc == 0) {
				walkTileMM(checkTile(randomTile(path[0])));
				return;
			}
			log("Bank Tile: " + path[0]);
			log("" + checkTile(randomTile(path[loc - 1])));
			walkTileMM(checkTile(randomTile(path[loc - 1])));
		} else {
			if (loc == path.length - 1) {
				walkTileMM(checkTile(randomTile(path[path.length - 1])));
				return;
			}
			walkTileMM(checkTile(randomTile(path[loc + 1])));
		}
	}

}
